import datetime
import random
import re

from flask import current_app, render_template, g, jsonify, redirect, url_for, request, session, abort, make_response

from info import db, constants, redis_store
from info.models import Order, House, User, Area, Facility
from info.modules.index import index_blu
from info.utils.captcha.captcha import captcha
from info.utils.common import user_login
from info.utils.response_code import RET


@index_blu.route('/imagecode')
def get_image_code():
    """
    图片验证码
    :return:
    """
    image_code_id = request.args.get('cur')
    per = request.args.get('per')

    if not image_code_id:
        abort(404)

    _, text, image = captcha.generate_captcha()
    current_app.logger.info('图片验证码为:%s' % text)

    try:
        redis_store.setex('ImageCodeId_' + image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        current_app.logger.error(e)
        abort(500)

    response = make_response(image)
    response.headers["Content-Type"] = "image/jpg"

    return response


@index_blu.route('/smscode', methods=['POST'])
def get_smscode():
    mobile = request.json.get('mobile')
    image_code = request.json.get('image_code')
    image_code_id = request.json.get('image_code_id')

    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')

    if not re.match(r"1[35678]\d{9}", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号的格式不正确")

    try:
        real_image_code = redis_store.get("ImageCodeId_" + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")

    if not real_image_code:
        return jsonify(errno=RET.NODATA, errmsg="图片验证码已经过期")

    if image_code.upper() != real_image_code.upper():
        return jsonify(errno=RET.DATAERR, errmsg="图片验证码输入错误")

    # 生成
    sms_code_str = "%06d" % random.randint(0, 999999)
    current_app.logger.info("短信验证码为%s" % sms_code_str)

    # 发送
    # result = CCP().send_template_sms(mobile, [sms_code_str, constants.SMS_CODE_REDIS_EXPIRES / 60], 1)
    #
    # if result != 0:
    #     return jsonify(errno=RET.THIRDERR, errmsg="短信验证码发送失败")

    # 存储
    try:
        redis_store.setex("SMS_" + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code_str)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="手机验证码保存失败")

    return jsonify(errno=RET.OK, errmsg="成功发送短信验证码")


@index_blu.route('/orders', methods=['POST'])
@user_login
def commit_order():
    """
    提交订单
    :return:
    """
    user = g.user

    start_date = request.json.get('start_date')
    end_date = request.json.get('end_date')
    house_id = request.json.get('house_id')

    # 验证 user_id house_id 需要存在
    if not all([start_date, end_date, house_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')

    try:
        house_id = int(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    if not user:
        return redirect(url_for('index.index'))

    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询失败')

    if not house:
        return jsonify(errno=RET.NODATA, errmsg='此房源不存在')

    # 提交订单
    try:
        order = Order()
        order.user_id = user.id
        order.house_id = house.id

        # str -> datetime.datetime
        start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
        end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d")

        order.begin_date = start_date
        order.end_date = end_date
        order.days = (end_date - start_date).days
        order.house_price = house.price
        order.amount = house.price * order.days

        db.session.add(order)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='数据库存储失败')

    data = {
        'order_id': order.id
    }

    return jsonify(errno=RET.OK, errmsg='订单已提交', data=data)


# @index_blu.route('/')
# def index():
#     return 'hello world'


@index_blu.route('/session', methods=['GET', 'DELETE', 'POST'])
@user_login
def check_state():
    """
    检查用户登录状态
    :return:
    """
    user = g.user
    if request.method == 'GET':
        data = {
            'user_id': user.id if user else None,
            'name': user.name if user else None
        }

        return jsonify(errno=RET.OK, errmsg='ok', data=data)

    elif request.method == 'DELETE':
        session.pop('user_id', None)
        return jsonify(errno=RET.OK, errmsg='退出成功')

    elif request.method == 'POST':
        mobile = request.json.get("mobile")
        password = request.json.get("password")

        if not all([mobile, password]):
            return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

        # 3、mobile  正则
        if not re.match(r"1[35678]\d{9}", mobile):
            return jsonify(errno=RET.PARAMERR, errmsg="手机号的格式不正确")

        try:
            user = User.query.filter_by(mobile=mobile).first()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据库查询错误")

        if not user:
            return jsonify(errno=RET.NODATA, errmsg="用户没有注册")

        if not user.check_passowrd(password):
            return jsonify(errno=RET.DATAERR, errmsg="密码输入错误")

        user.last_login = datetime.datetime.now()

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据保存失败")

        session["user_id"] = user.id

        return jsonify(errno=RET.OK, errmsg="登录成功")


# 甘宇飞
@index_blu.route("/user", methods=['GET', 'POST'])
@user_login
def get_user_info():
    """获取用户信息"""
    # 1.todo 判断用户是否登录
    # 2.查询数据
    if request.method == 'GET':
        user_id = session.get("user_id")
        try:
            user = User.query.get(user_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="查询数据库失败")
        # 3.返回数据

        return jsonify(errno=RET.OK, errmsg="Ok", data=user.to_dict())
    elif request.method == 'POST':
        mobile = request.json.get('mobile')
        phone_code = request.json.get('phonecode')
        password = request.json.get('password')

        if not all([mobile, phone_code, password]):
            return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')

        if not re.match(r"1[35678]\d{9}", mobile):
            return jsonify(errno=RET.PARAMERR, errmsg="手机号的格式不正确")

        try:
            real_sms_code = redis_store.get("SMS_" + mobile)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")

        if not real_sms_code:
            return jsonify(errno=RET.NODATA, errmsg="短信验证码已经过期")

        if real_sms_code != phone_code:
            return jsonify(errno=RET.DATAERR, errmsg="验证码输入错误")

        user = User()
        user.name = mobile
        user.password = password
        user.mobile = mobile

        try:
            db.session.add(user)
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据库保存失败")

        # 7、session保持用户登录状态
        session["user_id"] = user.id

        return jsonify(errno=RET.OK, errmsg="注册成功")


# 孙辉 3个
@index_blu.route('/houses', methods=['GET', 'POST'])
@user_login
def page_houses():
    """
    GET 查询  POST 发布新房源
    :return:
    """
    if request.method == 'GET':
        areaId = request.args.get('aid')
        startDate = request.args.get('sd')
        endDate = request.args.get('ed')
        sortKey = request.args.get('sk')
        next_page = request.args.get('p')
        if not all([areaId, startDate, endDate, sortKey]):
            return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
        if not next_page:
            next_page = 1
        try:
            next_page = int(next_page)
            areaId = int(areaId)
        except Exception as e:
            return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
        accommodation = datetime.datetime.strptime(endDate, "%Y-%m-%d") - datetime.datetime.strptime(startDate,
                                                                                                     "%Y-%m-%d")
        time = int(getattr(accommodation, 'days'))
        filters = []
        if sortKey == 'new':
            filters.append(House.create_time.desc())
        elif sortKey == 'booking':
            filters.append(House.order_count.desc())
        elif sortKey == 'price-inc':
            filters.append(House.price)
        elif sortKey == 'price-des':
            filters.append(House.price.desc())
        else:
            return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

        try:
            house = House.query.filter(House.area_id == areaId, House.min_days <= time,
                                       House.max_days >= time).order_by(
                *filters).paginate(next_page, constants.HOUSE_DETAIL_COMMENT_DISPLAY_COUNTS)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='数据库查询失败')

        house_all = house.items
        cur_page = house.page
        total_page = house.pages
        house_dict = [i.to_basic_dict() for i in house_all]
        print(house_dict)
        data = {
            "total_page": total_page,
            "houses": house_dict
        }
        return jsonify(errno=RET.OK, errmsg='OK', data=data)
    else:
        user = g.user
        house_data = request.get_json()
        if house_data is None:
            return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
        title = house_data.get("title")  # 房屋名称标题
        price = house_data.get("price")  # 房屋单价
        area_id = house_data.get("area_id")  # 房屋所属城区的编号
        address = house_data.get("address")  # 房屋地址
        room_count = house_data.get("room_count")  # 房屋包含的房间数目
        acreage = house_data.get("acreage")  # 房屋面积
        unit = house_data.get("unit")  # 房屋布局（几室几厅)
        capacity = house_data.get("capacity")  # 房屋容纳人数
        beds = house_data.get("beds")  # 房屋卧床数目
        deposit = house_data.get("deposit")  # 押金
        min_days = house_data.get("min_days")  # 最小入住天数
        max_days = house_data.get("max_days")  # 最大入住天数

        # 校验参数
        if not all([title, price, area_id, address, room_count, acreage, unit, capacity, beds, deposit, min_days,
                    max_days]):
            return jsonify(errno=RET.PARAMERR, errmsg="参数不完整")

        # 判断单价和押金格式是否正确
        # 前端传送过来的金额参数是以元为单位，浮点数，数据库中保存的是以分为单位，整数
        try:
            price = int(float(price) * 100)
            deposit = int(float(deposit) * 100)
        except Exception as e:
            return jsonify(errno=RET.DATAERR, errmsg="参数有误")

        # 保存信息
        # 创建房屋对象
        if max_days == '0':
            max_days = 99999
        house = House()

        house.user_id = user.id
        house.area_id = area_id
        house.title = title
        house.price = price
        house.address = address
        house.room_count = room_count
        house.acreage = acreage
        house.unit = unit
        house.capacity = capacity
        house.beds = beds
        house.deposit = deposit
        house.min_days = min_days
        house.max_days = max_days

        # 处理房屋的设施信息
        facility_ids = house_data.get("facility")
        if facility_ids:
            # 勾选了房屋设施
            # 过滤合理的设施id
            # select * from facility where id in (facility_ids)
            try:
                facility_list = Facility.query.filter(Facility.id.in_(facility_ids)).all()
            except Exception as e:
                current_app.logger.error(e)
                return jsonify(errno=RET.DBERR, errmsg="数据库异常")

            # 为房屋添加设施信息
            if facility_list:
                house.facilities = facility_list

        # 保存数据库
        try:
            db.session.add(house)
            db.session.commit()
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
            return jsonify(errno=RET.DBERR, errmsg="保存数据失败")

        # 四. 返回
        return jsonify(errno=RET.OK, errmsg="保存成功", data={"house_id": house.id})


@index_blu.route('/areas')
def area_all():
    """
    城区信息
    :return:
    """
    try:
        areas = Area.query.all()
    except Exception as e:
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    if not areas:
        return jsonify(errno=RET.NODATA, errmsg='无数据')
    data = [area.to_dict() for area in areas]
    # print(data)
    return jsonify(errno=RET.OK, errmsg='OK', data=data)


@index_blu.route('/houses/index')
def houses():
    """
    轮播图
    :return:
    """
    try:
        paginate = House.query.order_by(House.create_time.desc()).paginate(1, 5)
    except Exception as e:
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    if not paginate:
        return jsonify(errno=RET.NODATA, errmsg='无数据')
    room = paginate.items
    data = [house.to_basic_dict() for house in room]
    # print(data)
    return jsonify(errno=RET.OK, errmsg='OK', data=data)


@index_blu.route('/orders', methods=['PUT'])
def order_control():
    action = request.json.get('action')
    order_id = request.json.get('order_id')
    if not all([action, order_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')
    try:
        order_id = int(order_id)
    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    if action == "accept":
        try:
            order = Order.query.get(order_id)
        except Exception as e:
            return jsonify(errno=RET.DBERR, errmsg='数据库错误')
        if not order:
            return jsonify(errno=RET.DATAEXIST, errmsg='数据不存在')
        order.status = "WAIT_COMMENT"
        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            return jsonify(errno=RET.DBERR, errmsg='数据库错误')
        return jsonify(errno=RET.OK, errmsg='接受订单')

    elif action == "reject":
        reason = request.json.get('reason')
        if not reason:
            return jsonify(errno=RET.PARAMERR, errmsg='参数不全')
        try:
            order = Order.query.get(order_id)
        except Exception as e:
            return jsonify(errno=RET.DBERR, errmsg='数据库错误')
        if not order:
            return jsonify(errno=RET.DATAEXIST, errmsg='数据不存在')
        order.status = "REJECTED"
        order.comment = reason
        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            return jsonify(errno=RET.DBERR, errmsg='数据库错误')
        return jsonify(errno=RET.OK, errmsg='拒绝订单')
